#!/usr/bin/env python
import pygtk
pygtk.require("2.0")
import gtk, gobject
import sysaccess
from location import Location
from share import Share
from location_window import Location_Window
from share_window import Share_Window
from pygtk_threads import Pygtk_Thread
import threading

class Main_Window():
    def __init__(self):
        self.create_window()
        self.location = None
        self.locations = {}
        self.location_window = None
        self.share_window = None
        load = sysaccess.load()
        for location_name in load:
            self.Add_item(load[location_name])
        self.Refresh_Location_callback()
        self.Refresh_Share = gobject.timeout_add(5000, self.Refresh_Shares_callback)
        self.main()
    
    def create_window(self):
        self.window = gtk.Window(type=gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(600,450)
        #self.window.set_resizable(False)
        self.window.set_title("Sam")
        self.window.connect("destroy", self.destroy)
        self.window.connect("delete_event", self.delete_event)
        
        # Global VBox : Menu + Global VBox
        Global_VBox = gtk.VBox(False,5)
        
        # Menu
        self.create_menu()
        Global_VBox.pack_start(self.menu,False,False,10)
        
        # HBox : treeview + sep + right panel
        Global_HBox = gtk.HBox(False,5)
        Global_VBox.pack_start(Global_HBox,False,False,10)
        
        # Treeview
        Scrolled_Window = gtk.ScrolledWindow()
        Scrolled_Window.set_policy(gtk.POLICY_NEVER,gtk.POLICY_AUTOMATIC)
        self.create_treeview()
        Scrolled_Window.add(self.treeview)
        Global_HBox.pack_start(Scrolled_Window, True, True, 0)
        
        # Right panel
        Right_Panel_VBox = gtk.VBox(False,5)
        
        self.Lbl_Current_location = gtk.Label("Unknow location")
        Right_Panel_VBox.pack_start(self.Lbl_Current_location, False, False, 10)        
        
        Btn_Add_Location = gtk.Button("Add Location")
        Btn_Add_Location.connect("clicked", self.Add_Location_callback)
        Right_Panel_VBox.pack_start(Btn_Add_Location, False, False, 10)
        
        Btn_Add_Share = gtk.Button("Add Share")
        Btn_Add_Share.connect("clicked", self.Add_Share_callback)
        Right_Panel_VBox.pack_start(Btn_Add_Share, False, False, 10)
        
        Btn_Remove_Item = gtk.Button("Remove Item")
        Btn_Remove_Item.connect("clicked", self.Remove_item_callback)
        Right_Panel_VBox.pack_start(Btn_Remove_Item, False, False, 10)
        
        Btn_Edit = gtk.Button("Edit item")
        Btn_Edit.connect("clicked", self.Edit_item_callback)
        Right_Panel_VBox.pack_start(Btn_Edit, False, False, 10)
        
        Btn_Mount = gtk.Button("Mount")
        Btn_Mount.connect("clicked", self.Mount_callback)
        Right_Panel_VBox.pack_start(Btn_Mount, False, False, 10)
        
        Btn_Automount = gtk.Button("Automount")
        Btn_Automount.connect("clicked", self.Automount_callback)
        Right_Panel_VBox.pack_start(Btn_Automount, False, False, 10)
        
        Global_HBox.pack_end(Right_Panel_VBox,False,False,10)
        
        self.window.add(Global_VBox)
        self.window.show_all()
    
    def create_menu(self):
        self.UIManager = gtk.UIManager()
        self.UIManager_accel_group = self.UIManager.get_accel_group()
        self.window.add_accel_group(self.UIManager_accel_group)
        action_group = gtk.ActionGroup('UIManagerActionGroup')
        action_group.add_actions([('File',None,'_File'),
                                       ('Add Location',None,'_Add Location',None,'Add a location',self.Add_Location_callback),
                                       ('Add Share',None,'_Add Server',None,'Add a server',self.Add_Share_callback),
                                       ('Exit',gtk.STOCK_QUIT,'_Exit','<control>x','Exit SAM',self.Exit_callback),
                                       ('Edit',None,'_Edit'),
                                       ('Select All',None,'_Select All','<control>a','Select All'),
                                       ('Tools',None,'_Tools'),
                                       ('Refresh Location',None,'_Refresh Location',None,'Refresh Location',self.Refresh_Location_callback),
                                       ('Automount',None,'_Automount',None,'Automount',self.Automount_callback),
                                       ('Umount All',None,'_Umount All','<control>u','Umount All'),
                                       ('Load Defaults',None,'_Load Defaults',None,'Load Defaults',self.Load_Defaults_callback)])
        self.UIManager.insert_action_group(action_group,0)
        self.UIManager.add_ui_from_file('menu.xml')
        self.menu = self.UIManager.get_widget('/MenuBar')
        
    def create_treeview(self):
        self.treemodel = gtk.TreeStore( gobject.TYPE_STRING,
                                             gobject.TYPE_STRING,
                                             gobject.TYPE_BOOLEAN )
        self.treeview = gtk.TreeView(self.treemodel)
        
        Lbl_name = gtk.CellRendererText()
        Lbl_type = gtk.CellRendererText()    
        CB_active = gtk.CellRendererToggle()
        CB_active.connect('toggled', self.CB_Automount_callback)
        
        col_name = gtk.TreeViewColumn("Name", Lbl_name, text=0)
        col_type = gtk.TreeViewColumn("Type", Lbl_type, text=1)
        col_automount = gtk.TreeViewColumn("Auto", CB_active )
        col_automount.add_attribute(CB_active, "active", 2)
        
        self.treeview.append_column( col_name )
        self.treeview.append_column( col_type )
        self.treeview.append_column( col_automount )
    
    ##Privates methodes :
    
    def Get_item_iter(self,item):
            """return the item treeiter"""
            def search_item_iter(iter,value):
                """return item treeiter matching col0 == value"""
                if iter != None:
                    while self.treemodel.get_value(iter,0) != value: 
                        iter = self.treemodel.iter_next(iter)
                        if iter == None:
                            break
                return iter
            iter = self.treemodel.get_iter_first()
            if item.__class__.__name__ == "Location":
                iter = search_item_iter(iter, item.name)               
            elif item.__class__.__name__ == "Share":
                iter = search_item_iter(iter, item.location.name)
                iter = self.treemodel.iter_children(iter)
                iter = search_item_iter(iter,item.name)
            else:
                return None
            return iter
        
    def Get_item_by_path(self,path):
        """Return the item by the path"""
        if path.__class__.__name__ == "str":
            str_splited_path = path.split(':')
            splited_path = []
            for item in str_splited_path:
                splited_path.append(int(item))
                #put splited_path into a tuple to create a valid path
                path = tuple(splited_path)
        if len(path) == 1:
            return self.locations[self.treemodel[path][0]]
        elif len(path) == 2:
            return self.locations[self.treemodel[path[0]][0]].shares[self.treemodel[path][0]]
    
    def Add_item(self,item,index = None):
        if item.__class__.__name__ == "Location":
            if not item.name in self.locations:
                self.locations[item.name] = item 
                if index != None:
                    self.treemodel.insert(None,index,(item.name,"", item.automount))
                else:
                    self.treemodel.append(None,(item.name,"", item.automount))    
                for share_name in item.shares:
                    self.Add_item(item.shares[share_name])
        elif item.__class__.__name__ == "Share":
                self.locations[item.location.name].shares[item.name] = item
                if index != None:
                    self.treemodel.insert(self.Get_item_iter(item.location),index, (item.name,item.protocol, item.automount))
                else:
                    self.treemodel.append(self.Get_item_iter(item.location), (item.name,item.protocol, item.automount))
    
    def Remove_item(self,item):
        self.treemodel.remove(self.Get_item_iter(item))
        if item.__class__.__name__ == "Location":
            del self.locations[item.name]
        elif item.__class__.__name__ == "Share":
            del self.locations[item.location.name].shares[item.name]
    
    def Edit_item(self,item,path = None):
        iter = self.Get_item_iter(item)
        if not self.location_window or self.share_window:
            if item.__class__.__name__ == "Location":
                self.location_window = Location_Window(self.locations,item)
                new_location = self.location_window.main()
                if new_location:
                    self.Remove_item(item)
                    if path:
                        self.Add_item(new_location,path[0])
                    else:
                        self.Add_item(new_location)
                self.location_window = None
            elif item.__class__.__name__ == "Share":
                self.share_window = Share_Window(self.locations,item)
                new_share = self.share_window.main()
                if new_share:
                    self.Remove_item(item)
                    if path:
                        self.Add_item(new_share,path[1])
                    else:
                        self.Add_item(new_share)
            
    ## Callbacks:
    ## Treeview
    def CB_Automount_callback(self,cellrenderer, path):
        self.Get_item_by_path(path).automount = self.treemodel[path][2]
        self.treemodel[path][2] = not self.treemodel[path][2]
    
    ## Menu
    def Exit_callback(self,widget,data = None):
        sysaccess.save()
        self.destroy(widget)
    
    #Refresh share display
    def Refresh_Shares_callback(self):
        for location in self.locations:
            for share in self.locations[location].shares:
                Pygtk_Thread(self.Update_Share_thread_action,self.Update_Share_thread_callback,self.locations[location].shares[share]).start(self.locations[location].shares[share])
        return True
    
    def Update_Share_thread_action(self,share):
        ping = sysaccess.ping(share.get_server())
        if ping:
            share.latency = str(ping[1]) + ' ms'
        else:
            share.latency = "unreacheable"
   
    def Update_Share_thread_callback(self,share):
        self.treemodel.set_value(self.Get_item_iter(share),1,share.latency)
    
    #Refresh current location
    def Refresh_Location_callback(self,widget=None):
        Pygtk_Thread(self.Update_Current_Location_thread_action,self.Update_Current_Location_thread_callback).start()
    
    def Update_Current_Location_thread_action(self):
        self.ip = sysaccess.get_net_ip()
        for location in self.locations:
           if self.locations[location].domain != None:
               if self.locations[location].domain == self.ip:
                   self.location = self.locations[location].name
    
    def Update_Current_Location_thread_callback(self):
        if self.location != None:
            self.Lbl_Current_location.set_text(self.location + " " +self.ip)
        else :
            self.Lbl_Current_location.set_text("unknow")
    
        
    def Load_Defaults_callback(self,widget):
        self.locations.clear()
        self.treemodel.clear()
        
        home = Location('Home')
        home.shares["Public"] = Share('Public',home)
        home.shares["Public"].service = "//bandoine.hd.free.fr/plop"
        home.shares["Public"].mount_point = "//mnt/home/Public"
        self.Add_item(home)
        
        supinfo = Location('supinfo')
        supinfo.shares["Lyon2"] = Share('Lyon2',supinfo)
        supinfo.shares["Lyon2"].service = "//Lyon2.esi-supinfo.com/ephemere"
        supinfo.shares["Lyon2"].mount_point = "/mnt/supinfo/Lyon2"
        supinfo.shares["Paris2"] = Share('Paris2',supinfo)
        supinfo.shares["Paris2"].service = "//Paris2.esi-supinfo.com/ephemere"
        supinfo.shares["Lyon2"].mount_point = "/mnt/supinfo/Paris2"
        self.Add_item(supinfo)
        
    ## Right panel
    def Add_Location_callback(self, widget, data = None):
        if not self.location_window and not self.share_window:
            self.location_window = Location_Window(self.locations)
            new_location = self.location_window.main()
            self.Add_item(new_location)
            self.location_window = None
    
    def Add_Share_callback(self, widget, data = None):
        if not self.share_window and not self.location_window:
            self.share_window = Share_Window(self.locations)
            new_share = self.share_window.main()
            self.Add_item(new_share)
            self.share_window = None
            print "add share"
    
    def Remove_item_callback(self, widget, data = None):
        current_path = self.treeview.get_cursor()[0]
        if current_path != None:
            self.Remove_item(self.Get_item_by_path(current_path),current_path)
    
    def Edit_item_callback(self, widget, data = None):
        current_path = self.treeview.get_cursor()[0]
        if current_path != None:
            self.Edit_item(self.Get_item_by_path(current_path),current_path)
    
    def Mount_callback(self, widget, data = None):
        print "mount"
    
    def Automount_callback(self, widget, data = None):
        print "automount"

    ## window
    def delete_event(self, widget, event):
        sysaccess.save(self.locations)
        return False
      
    def destroy(self, widget):
       gtk.main_quit()
    
    def main(self):
        gtk.main()
        
if __name__ == '__main__':
    main_window = Main_Window()